home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of the portable Forth environment written in ANSI C.
- * Copyright (C) 1995 Dirk Uwe Zoller
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This file is version 0.9.13 of 17-July-95
- * Check for the latest version of this package via anonymous ftp at
- * roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
- * or sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
- * or ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
- *
- * Please direct any comments via internet to
- * duz@roxi.rz.fht-mannheim.de.
- * Thank You.
- */
- /*
- * helpindex.c --- read help files and create an index
- * (duz 13Sep94)
- */
-
- #define _XOPEN_SOURCE 1
- #define _ALL_SOURCE 1
-
- #include "config.h"
- #include "const.h"
- #include "options.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #if defined HAVE_GETOPT_H
- # include <getopt.h>
- #else
- # if defined HAVE_LIBC_H
- # include <libc.h>
- # endif
- # if defined HAVE_UNISTD_H
- # include <unistd.h>
- # endif
- #endif
-
- #include "missing.h" /* SEEK_SET */
- #include "help.h"
-
- #define NEW(P,N) ((P) = xalloc ((N) * sizeof *(P)))
-
- /*
- * Data structures.
- */
-
- typedef struct node Node; /* record in binary tree in memory */
- struct node
- {
- HRecord rec;
- Node *left, *right;
- };
-
- static HHeader hheader = {{'H', 'E', 'L', 'P'}};
- static char (*file)[PATH_LENGTH];
- static Node *root = NULL;
-
- static int
- insert (HRecord *new)
- /*
- * Insert *new into a binary tree starting at root.
- * Result: 1 if ok, 0 if record with same name already in tree.
- */
- {
- Node **p = &root, *q;
-
- while (*p != NULL)
- {
- int cmp = strcmp (new->name, (*p)->rec.name);
-
- if (cmp == 0)
- {
- fprintf (stderr, "\"%s\" is redefined\n", new->name);
- return 0;
- }
- if (cmp < 0)
- p = &(*p)->left;
- else if (cmp > 0)
- p = &(*p)->right;
- }
- NEW (q, 1);
- q->rec = *new;
- q->left = q->right = NULL;
- *p = q;
- return 1;
- }
-
- /*
- * Read records from file and insert them in the tree.
- */
-
- static long
- scan_record (FILE * f, char *name)
- /*
- * Reads the file until a `:' is found in column 0. Returns the name in *name.
- * Returns position of `:' or -1 at end of file.
- */
- {
- for (;;)
- {
- long pos = ftell (f);
- char line[0x80];
- char *p = fgets (line, sizeof line, f);
-
- if (p == NULL)
- {
- if (ferror (f))
- sys_error ();
- else
- return -1;
- }
- if (line[0] == ':')
- {
- sscanf (line, ":%s", name);
- return pos;
- }
- }
- }
-
- static void
- skip_record (FILE* f)
- /*
- * Skip over all lines in file until either two empty lines
- * or a `:' in column 0 is found.
- */
- {
- int empty = 0;
-
- for (;;)
- {
- long pos = ftell (f);
- char line[0x80];
- char *p = fgets (line, sizeof line, f);
-
- if (p == NULL)
- {
- if (ferror (f))
- sys_error ();
- else
- return;
- }
- if (line[0] == '\n' || line[0] == '#')
- {
- if (++empty == 2)
- return;
- else
- empty = 0;
- }
- if (line[0] == ':')
- {
- fseek (f, pos, SEEK_SET);
- return;
- }
- }
- }
-
- static void
- read_file (FILE *f, int fidx)
- {
- HRecord x;
-
- for (;;)
- {
- x.pos = scan_record (f, x.name);
- x.fidx = fidx;
- if (x.pos == -1)
- return;
- skip_record (f);
- if (insert (&x))
- hheader.nitems++;
- }
- }
-
- /*
- * Write file.
- */
-
- static void
- write_tree (Node *p, FILE * f)
- {
- if (p == NULL)
- return;
- write_tree (p->left, f);
- if (fwrite (&p->rec, sizeof p->rec, 1, f) != 1)
- sys_error ();
- write_tree (p->right, f);
- }
-
- static void
- write_file (FILE * f)
- {
- fwrite (&hheader, 1, sizeof hheader, f);
- fwrite (file, hheader.nfiles, sizeof *file, f);
- if (ferror (f))
- sys_error ();
- write_tree (root, f);
- }
-
- /*
- * Main program, process command line.
- */
-
- static void
- usage (void)
- {
- fatal ("usage:\t%s [-o file] file ..."
- "\n -o\toutput index to file (default: standard output)",
- progname);
- }
-
- int
- main (int argc, char *argv[])
- {
- char *outfile = NULL;
- FILE *in, *out;
- int c, i, n;
-
- /*
- * get program name for error messages
- */
- progname = strrchr (argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- /*
- * parse command line options
- */
- while ((c = getopt (argc, argv, ":ho:")) != EOF)
- {
- switch (c)
- {
- case '?':
- fatal ("illegal option %s", argv[optind]);
- case ':':
- fatal ("option %s requires an argument", argv[optind]);
- case 'h':
- usage ();
- case 'o':
- outfile = optarg;
- break;
- }
- }
- n = argc - optind;
- if (n <= 0)
- usage ();
-
- /*
- * process
- */
- hheader.nfiles = 0;
- hheader.nitems = 0;
- NEW (file, n);
- for (i = 0; i < n; i++)
- {
- strcpy (file[i], argv[optind + i]);
- in = fopen (file[i], "r");
- if (in == NULL)
- file_errorz (argv[i]);
- read_file (in, i);
- hheader.nfiles++;
- fclose (in);
- }
-
- if (outfile)
- {
- out = fopen (outfile, "wb");
- if (out == NULL)
- file_errorz (outfile);
- }
- else
- {
- out = stdout;
- }
- write_file (out);
- return 0;
- }
-